using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Windows.Controls;
using NUnit.Framework;
using SCSFContrib.CompositeUI.WPF.Workspaces;

namespace SCSFContrib.CompositeUI.WPF.UnitTest.Workspaces
{
	[TestFixture]
	public sealed class DeckWorkspaceTest : UnitTest
	{
		private DeckWorkspace _deckWorkspace;

		protected override void SetUpCore()
		{
			base.SetUpCore();
			_deckWorkspace = new DeckWorkspace();
		}

		[Test]
		public void Content_ShouldBeNullByDefault()
		{
			Assert.IsNull(_deckWorkspace.Content);
		}

		[Test]
		[ExpectedException(typeof(ArgumentNullException))]
		public void OnShow_ShouldThrowIfSmartPartIsNull()
		{
			_deckWorkspace.OnShow(null, new TabSmartPartInfo());
		}

		[Test]
		[ExpectedException(typeof(ArgumentNullException))]
		public void OnShow_ShouldThrowIfSmartPartInfoIsNull()
		{
			_deckWorkspace.OnShow("abc", null);
		}

		[Test]
		public void OnShow_ShouldPutSmartPartAtEndOfSmartPartsList()
		{
			Assert.IsEmpty(GetInnerSmartParts() as ICollection);
			_deckWorkspace.Show("abc");
			Assert.IsNotEmpty(GetInnerSmartParts() as ICollection);
			Assert.AreEqual("abc", GetInnerSmartParts()[0]);

			_deckWorkspace.Show("def");
			Assert.AreEqual("abc", GetInnerSmartParts()[0]);
			Assert.AreEqual("def", GetInnerSmartParts()[1]);
		}

		[Test]
		public void OnShow_ShouldAssignSmartPartsToContent()
		{
			Assert.IsNull(_deckWorkspace.Content);
			_deckWorkspace.Show("abc");
			Assert.AreSame("abc", _deckWorkspace.Content);

			_deckWorkspace.Show("def");
			Assert.AreSame("def", _deckWorkspace.Content);

			Button button = new Button();
			_deckWorkspace.Show(button);
			Assert.AreSame(button, _deckWorkspace.Content);
		}

		[Test]
		[ExpectedException(typeof(ArgumentNullException))]
		public void OnActivate_ShouldThrowIfSmartPartIsNull()
		{
			_deckWorkspace.OnActivate(null);
		}

		[Test]
		[ExpectedException(typeof(ArgumentException), ExpectedMessage = "smartPart is not present in this workspace.\r\nParameter name: smartPart")]
		public void OnActivate_ShouldThrowIfSmartPartIsNotFoundInWorkspace()
		{
			_deckWorkspace.OnActivate("abc");
		}

		[Test]
		public void OnActivate_ShouldPutSmartPartAtEndOfSmartPartsList()
		{
			_deckWorkspace.Show("abc");
			_deckWorkspace.Show("def");

			Assert.AreEqual("abc", GetInnerSmartParts()[0]);
			Assert.AreEqual("def", GetInnerSmartParts()[1]);
			_deckWorkspace.Activate("abc");
			Assert.AreEqual("def", GetInnerSmartParts()[0]);
			Assert.AreEqual("abc", GetInnerSmartParts()[1]);
		}

		[Test]
		public void OnActivate_ShouldAssignSmartPartsToContent()
		{
			Button button = new Button();
			_deckWorkspace.Show("abc");
			_deckWorkspace.Show("def");
			_deckWorkspace.Show(button);
			Assert.AreSame(button, _deckWorkspace.Content);

			_deckWorkspace.Activate("def");
			Assert.AreSame("def", _deckWorkspace.Content);

			_deckWorkspace.Activate("abc");
			Assert.AreSame("abc", _deckWorkspace.Content);

			_deckWorkspace.Activate(button);
			Assert.AreSame(button, _deckWorkspace.Content);
		}

		[Test]
		[ExpectedException(typeof(ArgumentNullException))]
		public void OnHide_ShouldThrowIfSmartPartIsNull()
		{
			_deckWorkspace.OnHide(null);
		}

		[Test]
		[ExpectedException(typeof(ArgumentException), ExpectedMessage = "smartPart is not present in this workspace.\r\nParameter name: smartPart")]
		public void OnHide_ShouldThrowIfSmartPartIsNotFoundInWorkspace()
		{
			_deckWorkspace.OnHide("abc");
		}

		[Test]
		public void OnHide_ShouldPutSmartPartAtStartOfSmartPartsList()
		{
			_deckWorkspace.Show("abc");
			_deckWorkspace.Show("def");

			Assert.AreEqual("abc", GetInnerSmartParts()[0]);
			Assert.AreEqual("def", GetInnerSmartParts()[1]);
			_deckWorkspace.Hide("def");
			Assert.AreEqual("def", GetInnerSmartParts()[0]);
			Assert.AreEqual("abc", GetInnerSmartParts()[1]);
		}

		[Test]
		public void OnHide_ShouldActivateSmartPartBehindTheHiddenSmartPart()
		{
			Button button = new Button();
			_deckWorkspace.Show("abc");
			_deckWorkspace.Show("def");
			_deckWorkspace.Show(button);
			Assert.AreSame(button, _deckWorkspace.Content);

			_deckWorkspace.Hide(button);
			Assert.AreSame("def", _deckWorkspace.Content);

			_deckWorkspace.Hide("def");
			Assert.AreSame("abc", _deckWorkspace.Content);

			_deckWorkspace.Hide("abc");
			Assert.AreSame(button, _deckWorkspace.Content);

			_deckWorkspace.Hide("def");
			Assert.AreSame(button, _deckWorkspace.Content);
		}

		[Test]
		[ExpectedException(typeof(ArgumentNullException))]
		public void OnClose_ShouldThrowIfSmartPartIsNull()
		{
			_deckWorkspace.OnClose(null);
		}

		[Test]
		[ExpectedException(typeof(ArgumentException), ExpectedMessage = "smartPart is not present in this workspace.\r\nParameter name: smartPart")]
		public void OnClose_ShouldThrowIfSmartPartIsNotFoundInWorkspace()
		{
			_deckWorkspace.OnClose("abc");
		}

		[Test]
		public void OnClose_ShouldActivateSmartPartBehindTheClosedSmartPart()
		{
			Button button = new Button();
			_deckWorkspace.Show("abc");
			_deckWorkspace.Show("def");
			_deckWorkspace.Show(button);
			Assert.AreSame(button, _deckWorkspace.Content);

			_deckWorkspace.Close(button);
			Assert.AreSame("def", _deckWorkspace.Content);

			_deckWorkspace.Close("def");
			Assert.AreSame("abc", _deckWorkspace.Content);

			_deckWorkspace.Close("abc");
			Assert.IsNull(_deckWorkspace.Content);
		}

		#region Supporting Methods

		private IList<object> GetInnerSmartParts()
		{
			return GetPrivateMemberValue<IList<object>>(_deckWorkspace, "InnerSmartParts");
		}

		#endregion
	}
}
